<template>
	<view class="m-progress-bar" :style="{ width: wrapperWidth + 'px' }" @click.stop="handleClick">
		<!-- 环形图区域 -->
		<view class="canvas-wrapper" :style="{ width: canvasSize + 'px', height: canvasSize + 'px' }">
			<canvas
				:id="'progressCanvas' + props.canvasId"
				:canvas-id="'progressCanvas' + props.canvasId"
				:style="{ width: canvasSize + 'px', height: canvasSize + 'px' }"
			></canvas>

			<!-- 中心内容 -->
			<view class="content-slot" :style="{ width: canvasSize + 'px', height: canvasSize + 'px' }">
				<slot name="content">
					<!-- <view class="default-text">{{ Math.round(props.progress) }}%</view> -->
				</slot>
			</view>
		</view>

		<!-- 底部文字 -->
		<view
			v-if="props.Text"
			class="bottom-text"
			:style="{
				color: props.BottomTextColor,
				fontSize: props.BottomTextSize + 'px'
			}"
		>
			{{ props.Text }}
		</view>
	</view>
</template>

<script lang="ts" setup name="mProgressCircle">
import { onMounted, watch, nextTick, getCurrentInstance, computed } from "vue"

const props = defineProps({
	canvasId: { type: String, default: "0" },
	progressColor: { type: String, default: "#FF0000" },
	trackColor: { type: String, default: "#CCCCCC" },
	progress: { type: Number, default: 0 },
	Text: { type: String, default: "" },
	BottomTextColor: { type: String, default: "#333" },
	radius: { type: Number, default: 50 },
	lineWidth: { type: Number, default: 10 },
	innerTextSize: { type: Number, default: 16 },
	innerTextColor: { type: String, default: "#333" },
	BottomTextSize: { type: Number, default: 16 },
	custom: { type: String, default: "" },
	bgColor: { type: String, default: "#FF0000" },
	textColor: { type: String, default: "#FFFFFF" },
	width: { type: Number, default: 80 }
})

const emit = defineEmits(["click"])
const handleClick = () => emit("click")

const instance = getCurrentInstance() as any
const sysDeviceInfo = JSON.parse(uni.getStorageSync("sysDeviceInfo") || "{}")
let ctx: any = null

// 固定宽度和画布大小
const wrapperWidth = computed(() => props.width)
const canvasSize = computed(() => props.radius * 2)

// 绘制函数
function drawProgress() {
	if (!ctx) return

	let percent = Math.min(100, Math.max(0, props.progress))
	const r = props.radius
	const lw = props.lineWidth

	// #ifdef APP-PLUS
	ctx.clearRect && ctx.clearRect(0, 0, r * 2, r * 2)
	// #endif

	// 底圈
	ctx.setLineWidth ? ctx.setLineWidth(lw) : (ctx.lineWidth = lw)
	ctx.setStrokeStyle ? ctx.setStrokeStyle(props.trackColor) : (ctx.strokeStyle = props.trackColor)
	ctx.beginPath && ctx.beginPath()
	ctx.arc(r, r, r - lw / 2, 0, 2 * Math.PI)
	ctx.stroke && ctx.stroke()

	// 进度圈
	if (ctx.setStrokeStyle) ctx.setStrokeStyle(props.progressColor)
	else ctx.strokeStyle = props.progressColor
	ctx.beginPath && ctx.beginPath()
	ctx.arc(r, r, r - lw / 2, -Math.PI / 2, (percent / 100) * 2 * Math.PI - Math.PI / 2)
	ctx.stroke && ctx.stroke()

	// 内部文字（仅微信/H5支持）
	if (ctx.fillText) {
		ctx.font = `${props.innerTextSize}px sans-serif`
		ctx.fillStyle = props.innerTextColor
		ctx.textAlign = "center"
		ctx.textBaseline = "middle"
		ctx.fillText(`${Math.round(percent)}%`, r, r)
	}

	// #ifdef APP-PLUS
	ctx.draw && ctx.draw()
	// #endif
}

// 初始化
function initCanvas() {
	// 微信小程序
	// #ifdef MP-WEIXIN
	const query = uni.createSelectorQuery().in(instance.proxy)
	query.select(`#progressCanvas${props.canvasId}`).node((res: any) => {
		if (!res?.node) return
		const canvas = res.node
		const dpr = sysDeviceInfo.pixelRatio || 1
		canvas.width = props.radius * 2 * dpr
		canvas.height = props.radius * 2 * dpr
		ctx = canvas.getContext("2d")
		ctx.scale(dpr, dpr)
		drawProgress()
	}).exec()
	// #endif

	// H5
	// #ifdef H5
	const canvas: any = document.getElementById(`progressCanvas${props.canvasId}`)
	if (canvas) {
		const dpr = window.devicePixelRatio || 1
		canvas.width = props.radius * 2 * dpr
		canvas.height = props.radius * 2 * dpr
		ctx = canvas.getContext("2d")
		ctx.scale(dpr, dpr)
		drawProgress()
	}
	// #endif

	// App
	// #ifdef APP-PLUS
	ctx = uni.createCanvasContext(`progressCanvas${props.canvasId}`, instance)
	drawProgress()
	// #endif
}

onMounted(async () => {
	await nextTick()
	setTimeout(() => {
		initCanvas()
	}, 50)
})

watch(() => props.progress, drawProgress)
</script>

<style scoped>
.m-progress-bar {
	display: flex;
	flex-direction: column;
	align-items: center;
	justify-content: center;
}

.canvas-wrapper {
	position: relative;
	display: flex;
	align-items: center;
	justify-content: center;
}

.content-slot {
	position: absolute;
	top: 0;
	left: 0;
	display: flex;
	align-items: center;
	justify-content: center;
	pointer-events: none;
}

.default-text {
	font-size: 14px;
	color: #333;
	text-align: center;
}

.bottom-text {
	margin-top: 8rpx;
	text-align: center;
}
</style>
